import 'package:flutter_ability/framework/http/adapter/dio_adapter.dart';
import 'package:flutter_ability/framework/http/adapter/hi_net_adapter.dart';
import 'package:flutter_ability/framework/http/request/base_request.dart';
import 'package:flutter_ability/framework/http/response/hi_error.dart';
import 'package:flutter_ability/framework/http/response/hi_response.dart';

/// 1.支持网络库插拔设计，且不干扰业务层
/// 2.基于配置请求请求，简洁易用
/// 3.Adapter设计，扩展性强
/// 4.统一异常和返回处理
class HiNet {
  HiNet._();

  static final HiNet _instance = HiNet._();

  factory HiNet() => _instance;

  /// 域名
  String? baseUrl = "";

  /// 登陆token
  Map<String, dynamic>? tokenHeader = {};

  /// 初始化
  Future<void> onInit({String? url, Map<String, dynamic>? token}) async {
    baseUrl = url;
    tokenHeader = token;
  }

  /// 发起请求
  Future _fire(BaseRequest request, HttpMethod method) async {
    HiResponse? response;
    dynamic error;
    HiNetAdapter adapter = DioAdapter();
    try {
      // 使用 Dio 发送请求
      switch (method) {
        case HttpMethod.GET:
          response = await adapter.get(request);
          break;
        case HttpMethod.POST:
          response = await adapter.post(request);
          break;
        case HttpMethod.DELETE:
          response = await adapter.delete(request);
          break;
      }
    } on HiError catch (e) {
      error = e;
      response = e.data;
      printLog(e.message);
    } catch (e) {
      error = e;
      printLog(e);
    }
    if (response == null) {
      printLog(error);
    }
    var result = response?.data;
    var status = response?.statusCode;
    Exception hiError;
    switch (status) {
      case 200:
        return result;
      case 401:
        hiError = NeedLogin();
        break;
      case 403:
        hiError = NeedAuth(result.toString(), data: result);
        break;
      default:
        hiError =
            error ?? HiError(status ?? -1, result.toString(), data: result);
        break;
    }
    throw hiError;
  }

  void printLog(log) {
    print('hi_net:${log.toString()}');
  }

  Future delete<T>(BaseRequest request) {
    return _fire(request, HttpMethod.DELETE);
  }

  Future get<T>(BaseRequest request) {
    return _fire(request, HttpMethod.GET);
  }

  Future post<T>(BaseRequest request) {
    return _fire(request, HttpMethod.POST);
  }
}
